<?php
namespace app\extensions\lib;
use app\extensions\lib\push\BasePush;
use app\extensions\lib\push\Push;
use app\model\TokenInfo;
use app\queue\redis\shushu\DeviceEvent;
use support\Log;
use support\Redis;

class Fcm
{
    public static function push($project_id,$access_token,$message=[],$package_id=0,$request_id=''){
        $url = "https://fcm.googleapis.com/v1/projects/{$project_id}/messages:send";
        $tokens = $message['message']['tokens'];
        $udids = $message['message']['udids'];
        unset($message['message']['udids'],$message['message']['tokens']);
        $tokens = array_filter(explode(',',$tokens));
        $udids = array_filter(explode(',',$udids));
        $header = [
            //'Connection: Keep-Alive',
            //'Keep-Alive: 300',
            'Accept:application/json',
            //'Content-Length:'.strlen(json_encode($params)),
            'Content-Type: application/json',
            'Authorization: Bearer '.$access_token,
        ];
        /*$response = curl($url,json_encode($message),1,$header);
        Log::channel('fcm')->info($response);*/

        //消息体信息
        $title = $message['message']['notification']['title'] ?? '';
        $content = $message['message']['notification']['body'] ?? '';
        $message_type = self::getMessageType($message);
        $image = $message['message']['notification']['image'] ?? '';

        $Event = new DeviceEvent();
        $sockets = [];
        $eventIds = [];
        $multiSockets = curl_multi_init();

        foreach ($tokens as $key => $token) {
            $sockets[$key] = curl_init();
            $udid = $udids[$key] ?? 'no udid';
            $message['message']['token'] = $token;
            $eventIds[$key] = $eventId = getEventId($package_id,uniqid($udid));//事件Id
            $message['message']['data']['message_id'] = $eventId;//透传消息id
            $message['message']['data']['udid'] = $udid;//透传消息udid
            if(env('APP_ENV')!='production'){
                dump($message);
            }
            curl_setopt_array($sockets[$key], array(
                // 2.带上deviceToken向APNs服务器请求
                CURLOPT_URL => $url,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,
                CURLOPT_TIMEOUT => 5,
                CURLOPT_CUSTOMREQUEST => "POST",
                // 3.把推送的payload放入请求体+设置请求头
                CURLOPT_POSTFIELDS => json_encode($message),
                CURLOPT_HTTPHEADER => $header,
            ));
            curl_multi_add_handle($multiSockets, $sockets[$key]);
        }

        $running = null;
        $request_time = date('Y-m-d H:i:s');
        do {
            curl_multi_exec($multiSockets, $running);
        } while ($running > 0);

        $responses = [];
        $valid = $error = $success = 0;
        $delToken = [];
        foreach ($sockets as $key =>$h) {
            $udid = $udids[$key] ?? 'no udid';
            $eventId = $eventIds[$key];
            $info = curl_getinfo($h);
            $total_time = (($info['total_time'] ?? 0) * 1000).'ms';
            $responseStr = curl_multi_getcontent($h);
            $response = json_decode($responseStr,true);
            $code = '';
            $status = 0;
            $token = $tokens[$key] ?? 'no found token';
            $prefixLog = "$request_id:$udid:$token===time:$total_time:".json_encode($response);
            if(isset($response['error'])){
                Log::channel('fcm')->warning($prefixLog);
                $error++;
                try{
                    if($response['error']['code']==404){
                        $delToken[] = $token;
                        $valid++;
                    }
                    if($response['error']['code']==400 && $response['error']['message']=='The registration token is not a valid FCM registration token'){
                        $delToken[] = $token;
                        $valid++;
                    }
                }catch (\Throwable $e){
                    Log::channel('fcm')->error($prefixLog.'判断失效token 错误:'.$e->getMessage());
                }
                $code = $response['error']['code'] ?? '';
            }else{
                $status = 1;
                $name = $response['name'] ?? '';
                /*if($name){
                    $message_id = implode('_',explode('/',$name));
                }*/
                $success++;
                Log::channel('fcm')->info($prefixLog);
            }
            curl_multi_remove_handle($multiSockets, $h);
            //设备记录上传

            $other = json_decode(Redis::get(Push::getPayloadKey($request_id)),true) ?:[];
            $properties = [
                    'title' => $title,
                    'content' => $content,
                    'image' => $image,
                    'message_type' => $message_type,
                    'request_id' => $request_id,
                    '#ip' => '',
                    'os_id' => '1',
                    'package_id' => $package_id,
                    'token' => $token,
                    'code' => strval($code),
                    'status' => strval($status),
                    'sdk_info' => compact('project_id'),
                    'result' => $responseStr,
                    'request_time' => $request_time
                ] + $other;

            \Webman\RedisQueue\Redis::send($Event->queue,[
                'package_id' => $package_id,
                'params' => [
                    'track_update',
                    '',
                    $udid,
                    $properties,
                    BasePush::EVENT_DEVICE_PUSH_LOG,
                    $eventId
                ],
            ]);
        }

        if (is_resource($multiSockets)) {
            curl_multi_close($multiSockets);
        }
        if (!empty($sockets)) {
            foreach ($sockets as $val) {
                if (is_resource($val)) {
                    curl_close($val);
                }
            }
        }
        if($delToken){
            $TokenInfo = new TokenInfo();
            $TokenInfo->refreshInvalid($delToken);
        }
        return compact('success','error','valid');
    }

    private static function getMessageType(array $message)
    {
        $type = 1;
        if(isset($message['message']['notification'])){
            $type = 0;
        }
        return $type;
    }


    public function sendDeviceGroup($send_id,$serverKey,$groupId){
        $url = 'https://fcm.googleapis.com/fcm/send';
        $header = [
            'Content-Type: application/json',
            'Authorization: key='.$serverKey,
            'project_id:'.$send_id,
        ];
        $params = [
            'to'=>$groupId,
            'data' => [
                'title' =>'title',
                'body' =>'body',
            ],
            'notification' => [
                'title' =>'title',
                'body' =>'body',
            ],
        ];
        return curl($url,json_encode($params),1,$header);
    }

    public function getDeviceGroup($send_id,$serverKey,$groupName){
        $url = 'https://fcm.googleapis.com/fcm/notification?notification_key_name='.$groupName;
        $header = [
            'Content-Type: application/json',
            'Authorization: key='.$serverKey,
            'project_id:'.$send_id,
        ];
        return curl($url,[],1,$header);
    }

    public function deleteDeviceGroup($send_id,$serverKey,$tokens,$groupId,$groupName){
        $header = [
            //'Content-Length:'.strlen(json_encode($params)),
            'Content-Type: application/json',
            'Authorization: key='.$serverKey,
            'project_id:'.$send_id,
        ];
        $operation = 'remove';
        $url = 'https://fcm.googleapis.com/fcm/notification';
        $params = [
            'operation'=>$operation,
            'notification_key_name' => $groupName,
            'registration_ids' => $tokens
        ];
        if($groupId){
            $params['notification_key'] = $groupId;
        }
        return curl($url,json_encode($params),1,$header);
    }

    public function createDeviceGroup($send_id,$serverKey,$groupName,$tokens){

        $data = $this->getDeviceGroup($send_id,$serverKey,$groupName);
        $data = json_decode($data,true) ?: [];
        $operation = 'create';
        if(isset($data['notification_key']) && $data['notification_key']){
            $operation = 'add';
            $notification_key = $data['notification_key'];
        }
        $header = [
            //'Content-Length:'.strlen(json_encode($params)),
            'Content-Type: application/json',
            'Authorization: key='.$serverKey,
            'project_id:'.$send_id,
        ];
        $url = 'https://fcm.googleapis.com/fcm/notification';
        $params = [
            'operation'=>$operation,
            'notification_key_name' => $groupName,
            'registration_ids' => $tokens
        ];
        if(isset($notification_key)){
            $params['notification_key'] = $notification_key;
        }
        $return = curl($url,json_encode($params),1,$header);
        return $return;
    }

}
